<template>
  <div class="content-area">
    <div>
      <div class="kg_head">
        <div class="kg_head_title">
          <span class="kg_head_logo"></span>
          <span>设备运维知识图谱</span>
        </div>
        <div class="kg_head_btn" @click="resetGraph">重置图谱</div>
        <div class="kg_head_search">
          <el-autocomplete
            v-model="searchInput"
            :fetch-suggestions="querySearchAsync"
            placeholder="请输入节点关键字"
            @select="handleSelect"
          ></el-autocomplete>
        </div>
      </div>
      <div class="kg_content">
        <div id="kg_container" class="kg_content_kg"></div>
        <div class="kg_content_search">
          <div class="search_head">节点信息:</div>
          <div>
            <div class="search_head">
              <span>{{ defaultNode }}</span>
            </div>
            <div class="search_entity_info">
              <span
                >采煤机是一种用于煤矿井下采煤作业的重型机械设备，通常配合长壁采煤工作面进行作业。它通过电动机驱动截割装置（包括截割滚筒或截齿），将煤层从岩壁上切割下来，然后通过刮板输送机或其他传送设备将煤炭运送到矿井地面。采煤机主要由机身、截割装置、行走装置、运输装置、电控系统等组成。</span
              >
            </div>
          </div>
          <div class="search_head">关联结果:</div>
          <div class="result">
            <div class="result-item">
              <span>主要设备</span>
            </div>
            <div class="result-item">
              <span>皮带机</span>
            </div>
            <div class="result-item">
              <span>电动机</span>
            </div>
            <div class="result-item">
              <span>传感器</span>
            </div>
            <div class="result-item">
              <span>管路</span>
            </div>
            <div class="result-item">
              <span>煤矿</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'
import { Graph } from '@antv/g6' // <-- 修改这里，导入 Graph 类

// 模拟后端请求函数 (保持不变)
const queryNodeByName = async (node_name, level) => {
  console.log(`Mock: Querying node by name: ${node_name}, level: ${level}`)
  await new Promise((resolve) => setTimeout(resolve, 500)) // 模拟网络延迟

  if (node_name === '采煤机') {
    return {
      data: {
        nodes: [
          { id: '采煤机', label: '采煤机', style: { fill: '#00cac7' } },
          { id: '截割装置', label: '截割装置' },
          { id: '行走装置', label: '行走装置' },
          { id: '运输装置', label: '运输装置' },
          { id: '电控系统', label: '电控系统' },
          { id: '电动机', label: '电动机' },
          { id: '传感器', label: '传感器' },
          { id: '皮带机', label: '皮带机' },
          { id: '煤矿', label: '煤矿' },
        ],
        edges: [
          { source: '采煤机', target: '截割装置', label: '组成部分' },
          { source: '采煤机', target: '行走装置', label: '组成部分' },
          { source: '采煤机', target: '运输装置', label: '组成部分' },
          { source: '采煤机', target: '电控系统', label: '组成部分' },
          { source: '截割装置', target: '电动机', label: '驱动' },
          { source: '运输装置', target: '皮带机', label: '包含' },
          { source: '电控系统', target: '传感器', label: '包含' },
          { source: '采煤机', target: '煤矿', label: '用于' },
        ],
      },
    }
  } else if (node_name === '电动机') {
    return {
      data: {
        nodes: [
          { id: '电动机', label: '电动机', style: { fill: '#00cac7' } },
          { id: '采煤机', label: '采煤机' },
          { id: '风机', label: '风机' },
          { id: '水泵', label: '水泵' },
        ],
        edges: [
          { source: '电动机', target: '采煤机', label: '用于' },
          { source: '电动机', target: '风机', label: '用于' },
          { source: '电动机', target: '水泵', label: '用于' },
        ],
      },
    }
  } else if (node_name === '传感器') {
    return {
      data: {
        nodes: [
          { id: '传感器', label: '传感器', style: { fill: '#00cac7' } },
          { id: '电控系统', label: '电控系统' },
          { id: '温度传感器', label: '温度传感器' },
          { id: '压力传感器', label: '压力传感器' },
        ],
        edges: [
          { source: '传感器', target: '电控系统', label: '属于' },
          { source: '传感器', target: '温度传感器', label: '类型' },
          { source: '传感器', target: '压力传感器', label: '类型' },
        ],
      },
    }
  }
  return {
    data: {
      nodes: [{ id: node_name, label: node_name, style: { fill: '#00cac7' } }],
      edges: [],
    },
  }
}

const queryNodeList = async (queryString) => {
  console.log('Mock: Querying node list for:', queryString)
  await new Promise((resolve) => setTimeout(resolve, 200)) // 模拟网络延迟

  const mockNodes = [
    { value: '采煤机' },
    { value: '电动机' },
    { value: '传感器' },
    { value: '皮带机' },
    { value: '煤矿' },
    { value: '风机' },
    { value: '水泵' },
    { value: '截割装置' },
    { value: '行走装置' },
    { value: '运输装置' },
    { value: '电控系统' },
    { value: '温度传感器' },
    { value: '压力传感器' },
  ]
  return {
    data: queryString ? mockNodes.filter((node) => node.value.includes(queryString)) : mockNodes,
  }
}

const searchInput = ref('')
const kgData = ref({})
const nodeList = ref([])
const defaultNode = ref('采煤机')
const defaultLevel = ref(1)
const timeout = ref(null)
const graph = ref(null)

const searchNodeByName = async (node_name) => {
  try {
    const res = await queryNodeList(node_name)
    nodeList.value = res.data
  } catch (err) {
    console.error(err)
    console.error('系统请求异常！')
  }
}

const selectNode = async (node_name) => {
  try {
    const res = await queryNodeByName(node_name, defaultLevel.value)
    kgData.value = res.data
    if (graph.value) {
      graph.value.changeData(kgData.value)
      graph.value.fitView()
    } else {
      renderGraph(kgData.value)
    }
  } catch (err) {
    console.error(err)
    console.error('系统请求异常！')
  }
}

const renderGraph = (data) => {
  const container = document.getElementById('kg_container')
  if (!container) {
    console.error("G6 container 'kg_container' not found!")
    return
  }

  // 确保在组件卸载或重新渲染时销毁旧的图谱实例
  if (graph.value) {
    graph.value.destroy()
    graph.value = null
  }

  graph.value = new Graph({
    // <-- 修改这里，使用导入的 Graph 类
    container: 'kg_container',
    width: container.offsetWidth,
    height: container.offsetHeight,
    linkCenter: true,
    animate: true,
    animateCfg: {
      duration: 1000,
      easing: 'easeSinIn',
    },
    modes: {
      default: [
        {
          type: 'collapse-expand',
          onChange: function onChange(item, collapsed) {
            const model = item.get('model')
            model.collapsed = collapsed
            return true
          },
        },
        'drag-canvas',
        'zoom-canvas',
        'drag-node',
      ],
    },
    layout: {
      type: 'fruchterman',
      gravity: 5,
      speed: 5,
    },
    defaultNode: {
      size: 26,
      style: {
        fill: '#37747f',
      },
      labelCfg: {
        style: {
          fill: '#fff',
          fontSize: 14,
        },
        position: 'bottom',
      },
    },
    defaultEdge: {
      size: 1,
      color: '#e2e2e2',
      style: {
        endArrow: {
          path: 'M 4,0 L -4,-4 L -4,4 Z',
          d: 4,
        },
      },
    },
  })

  graph.value.on('node:click', (evt) => {
    console.log('Node clicked:', evt.item.get('model'))
    const nodeModel = evt.item.get('model')
    defaultNode.value = nodeModel.label || nodeModel.id
    // selectNode(nodeModel.id); // 取消注释可以实现点击节点展开
  })

  graph.value.data(data)
  graph.value.render()
  graph.value.fitView()
}

const querySearchAsync = (queryString, cb) => {
  if (timeout.value) {
    clearTimeout(timeout.value)
  }
  timeout.value = setTimeout(async () => {
    try {
      const res = await queryNodeList(queryString)
      cb(res.data)
    } catch (err) {
      console.error(err)
      console.error('系统请求异常！')
      cb([])
    }
  }, 300 * Math.random())
}

const handleSelect = (item) => {
  searchInput.value = item.value // 确保选中后搜索框显示完整值
  defaultNode.value = item.value
  selectNode(item.value)
}

const resetGraph = () => {
  defaultNode.value = '采煤机'
  searchInput.value = ''
  selectNode(defaultNode.value)
}

onMounted(() => {
  // 确保 DOM 元素已经存在，G6才能渲染
  nextTick(() => {
    selectNode(defaultNode.value)
  })

  // 监听窗口大小变化，调整图谱尺寸
  // 由于 G6 需要具体的容器尺寸，当容器大小变化时需要更新 G6 的 canvas
  const resizeObserver = new ResizeObserver((entries) => {
    for (let entry of entries) {
      if (entry.target.id === 'kg_container' && graph.value) {
        graph.value.changeSize(entry.contentRect.width, entry.contentRect.height)
        graph.value.fitView() // 适应视图
      }
    }
  })
  const kgContainer = document.getElementById('kg_container')
  if (kgContainer) {
    resizeObserver.observe(kgContainer)
  }

  // 组件卸载时停止观察
  onUnmounted(() => {
    // 将 unobserve 放到 onUnmounted 中
    if (kgContainer) {
      resizeObserver.unobserve(kgContainer)
    }
    if (graph.value) {
      // 确保在组件卸载时销毁 G6 实例
      graph.value.destroy()
      graph.value = null
    }
    if (timeout.value) {
      // 清除未完成的定时器
      clearTimeout(timeout.value)
    }
  })
})

// onUnmounted 钩子中的内容已移至 onMounted 的返回函数中，或单独定义。
// 在这里重新声明 onUnmounted 确保在组件卸载时执行清理
// 注意：如果 onMounted 内部的 onUnmounted 是在组件创建时立即注册的，
// 那么它会在组件销毁时正确运行。这种写法是安全的。
// 例如：
// onMounted(() => {
//   // setup resizeObserver
//   return () => { // This function runs when component is unmounted
//     // cleanup resizeObserver and graph
//   }
// })
// 这里为了清晰，我把 onUnmounted 单独拿出来了。
</script>

<style scoped>
/* content-area 的基础样式已经在全局 style.css 中，这里仅作为容器 */
.content-area {
  flex: 1;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  overflow-y: auto;
  background-color: #f0f2f5;
}

/* 知识图谱页面特有样式 */
.kg_head {
  height: 45px;
  width: 100%;
  display: flex; /* 使用 flex 布局 */
  align-items: center; /* 垂直居中 */
  margin-bottom: 10px; /* 顶部和内容之间的间距 */
}

.kg_head_title {
  display: flex;
  align-items: center;
  margin-right: auto; /* 将标题推到左边，其他按钮推到右边 */
}

.kg_head_logo {
  margin-right: 10px;
  display: inline-block;
  width: 28px;
  height: 28px;
  background-image: url('/kg.svg'); /* 确保 kg.svg 放在 public 目录下 */
  background-size: cover;
  filter: invert(1) sepia(1) hue-rotate(180deg); /* 模拟原始效果 */
  transform: translateY(2px); /* 微调位置 */
}

.kg_head_title span {
  font-size: 28px;
  line-height: 45px;
  font-weight: 400;
  color: #333; /* 确保标题颜色可见 */
}

.kg_head_btn {
  width: 100px; /* 调整按钮宽度 */
  height: 40px;
  background-color: darkcyan;
  color: white;
  border-radius: 4px;
  margin-left: 10px; /* 按钮之间间距 */
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background-color 0.3s ease;
}

.kg_head_btn:hover {
  background-color: #008b8b; /* 悬停效果 */
}

.kg_head_search {
  width: 250px; /* 调整搜索框宽度 */
  margin-left: 20px; /* 与按钮的间距 */
}

.kg_content {
  display: flex;
  justify-content: center; /* 保持水平居中图谱和信息面板 */
  width: 100%;
  flex: 1; /* 占据 content-area 的剩余垂直空间 */
  background-color: #2b2f33; /* 背景色 */
  border-radius: 8px; /* 圆角 */
  overflow: hidden; /* 防止内容溢出 */
  gap: 20px; /* 图谱和搜索面板之间的间距 */
  padding: 10px; /* 内部填充 */
  box-sizing: border-box; /* 确保 padding 不会撑大容器 */
}

.kg_content_kg {
  width: calc(100% - 380px); /* 动态计算宽度，为搜索面板留出空间 */
  height: 100%; /* 占据 kg_content 的所有垂直空间 */
  min-height: 800px;
  height: 100%;
  background-color: #3a4045; /* G6画布背景色 */
  border-radius: 5px;
  overflow: hidden; /* 防止G6渲染内容溢出 */
  border: 1px solid #00cac7; /* 边框 */
}

.kg_content_search {
  height: 100%; /* 占据 kg_content 的所有垂直空间 */
  width: 360px; /* 固定宽度 */
  color: white;
  background-color: #43727e;
  padding: 10px;
  border-radius: 5px;
  border: solid 1px #00cac7;
  overflow-y: auto; /* 允许内容滚动 */
  flex-shrink: 0; /* 防止搜索面板收缩 */
}

.search_head {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 10px;
  padding-bottom: 5px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.search_entity_info {
  margin-bottom: 20px;
  line-height: 1.5;
  font-size: 14px;
}
.search_entity_info span {
  display: block;
}

.result {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.result-item {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 110px;
  height: 30px;
  background-color: #00cac7;
  border-radius: 4px;
  font-weight: 600;
  color: #ffffff;
  cursor: pointer;
  transition: background-color 0.3s ease;
}
.result-item:hover {
  background-color: #00a0a0;
}
</style>
